﻿using System;
using Kaleida.ServiceMonitor.Framework;
using NUnit.Framework;

namespace Kaleida.UnitTests.Framework
{
    [TestFixture]
    public class DataSizeParserTests
    {
        [Test]
        public void TestCanParseBytes()
        {
            TestCanParse("123", "123 bytes", DataSize.FromBytes(123));
            TestCanParse("1b", "1 bytes", DataSize.FromBytes(1));
            TestCanParse("-1b", "-1 bytes", DataSize.FromBytes(-1));
            TestCanParse("-2b", "-2 bytes", DataSize.FromBytes(-2));
            TestCanParse(" 4b ", "4 bytes", DataSize.FromBytes(4));
            TestCanParse(" 4B ", "4 bytes", DataSize.FromBytes(4));
            TestCanParse("4 byte", "4 bytes", DataSize.FromBytes(4));
            TestCanParse("4 bYtE", "4 bytes", DataSize.FromBytes(4));
            TestCanParse("4 bytes", "4 bytes", DataSize.FromBytes(4));
            TestCanParse("4 bYteS", "4 bytes", DataSize.FromBytes(4));
        }

        [Test]
        public void TestCanParseKilobytes()
        {
            TestCanParse("1kb", "1 KB", DataSize.FromKilobytes(1));
            TestCanParse("-1kb", "-1 KB", DataSize.FromKilobytes(-1));
            TestCanParse("-2kb", "-2 KB", DataSize.FromKilobytes(-2));
            TestCanParse(" 4kb ", "4 KB", DataSize.FromKilobytes(4));
            TestCanParse(" 4KB ", "4 KB", DataSize.FromKilobytes(4));
            TestCanParse("4 kilobyte", "4 KB", DataSize.FromKilobytes(4));
            TestCanParse("4 kiLobYte", "4 KB", DataSize.FromKilobytes(4));
            TestCanParse("4 kilobytes", "4 KB", DataSize.FromKilobytes(4));
            TestCanParse("4 kIlobYteS", "4 KB", DataSize.FromKilobytes(4));
        }

        [Test]
        public void TestCanParseMegabytes()
        {
            TestCanParse("1mb", "1 MB", DataSize.FromMegabytes(1));
            TestCanParse("-1mb", "-1 MB", DataSize.FromMegabytes(-1));
            TestCanParse("-2mb", "-2 MB", DataSize.FromMegabytes(-2));
            TestCanParse(" 4mb ", "4 MB", DataSize.FromMegabytes(4));
            TestCanParse(" 4MB ", "4 MB", DataSize.FromMegabytes(4));
            TestCanParse("4 megabyte", "4 MB", DataSize.FromMegabytes(4));
            TestCanParse("4 meGabYte", "4 MB", DataSize.FromMegabytes(4));
            TestCanParse("4 megabytes", "4 MB", DataSize.FromMegabytes(4));
            TestCanParse("4 meGAbYteS", "4 MB", DataSize.FromMegabytes(4));
        }

        [Test]
        public void TestCanParseGigabytes()
        {
            TestCanParse("1gb", "1 GB", DataSize.FromGigabytes(1));
            TestCanParse("-1gb", "-1 GB", DataSize.FromGigabytes(-1));
            TestCanParse("-2gb", "-2 GB", DataSize.FromGigabytes(-2));
            TestCanParse(" 4gb ", "4 GB", DataSize.FromGigabytes(4));
            TestCanParse(" 4GB ", "4 GB", DataSize.FromGigabytes(4));
            TestCanParse("4 gigabyte", "4 GB", DataSize.FromGigabytes(4));
            TestCanParse("4 gIgabYte", "4 GB", DataSize.FromGigabytes(4));
            TestCanParse("4 gigabytes", "4 GB", DataSize.FromGigabytes(4));
            TestCanParse("4 GiGabYteS", "4 GB", DataSize.FromGigabytes(4));
        }

        [Test]
        public void TestCannotParseBadInput()
        {
            Assert.IsFalse(DataSizeParser.CanParse("mb1"));
            Assert.IsFalse(DataSizeParser.CanParse("-1-mb"));
            Assert.IsFalse(DataSizeParser.CanParse("abc"));
            Assert.IsFalse(DataSizeParser.CanParse("123abc"));
        }

        [Test, ExpectedException(typeof(FormatException), ExpectedMessage = "Cannot parse '123 abc' as a DataSize. The following suffices may be used: GB, MB, KB, byte")]
        public void TestExceptionIsThrownIfTryParseDataSizeWithBadInput()
        {
            DataSizeParser.ParseDataSize("123 abc");
        }

        private static void TestCanParse(string input, string expectedCanonicalised, DataSize expectedSize)
        {
            Assert.IsTrue(DataSizeParser.CanParse(input), "Expected to be able to parse '{0}'", input);
            Assert.AreEqual(expectedCanonicalised, DataSizeParser.ParseDataSize(input).ToString(), "expected canonical representation of '{0}' to be '{1}'", input, expectedCanonicalised);
            Assert.AreEqual(expectedSize.ValueInBytes, DataSizeParser.ParseDataSize(input).ValueInBytes, "expected DataSize of '{0}' to be '{1}'", input, expectedSize.ToFormattedString());
        }
    }
}
